/*
 * @Author: 杰编程 2306248989@qq.com
 * @Date: 2023-08-08 15:31:44
 * @LastEditors: 杰编程 2306248989@qq.com
 * @LastEditTime: 2023-08-08 15:51:43
 * @FilePath: /lesson27/Http/HttpServer.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <iostream>
#include<functional>
#include "Sock.hpp"
#include "Log.hpp"
#include "Ulit.hpp"
#include <pthread.h>

const uint16_t defaultprot = 8888;
using func_t = std::function<std::string(const std::string&)>;

class HttpServer;
struct pthreadData
{
    pthreadData(HttpServer *ts, int sockfd, std::string clientip, uint16_t clientport)
        : _ts(ts), _sockfd(sockfd), _clientip(clientip), _clientport(clientport)
    {
    }
    HttpServer *_ts;
    int _sockfd;
    std::string _clientip;
    uint16_t _clientport;
};

class HttpServer
{
public:
    HttpServer(func_t func,uint16_t port = defaultprot)
        : _port(port),
        _func(func)
    {
    }

    void InitServer()
    {
        _listensock.Socket();
        _listensock.Bind(_port);
        _listensock.Listen();
    }

    static void *threadRoutine(void *args)
    {
        pthread_detach(pthread_self());
        pthreadData *pd = static_cast<pthreadData *>(args);
        pd->_ts->Server(pd->_sockfd, pd->_clientip, pd->_clientport);

        delete pd;
        return nullptr;
    }
    void Server(int sockfd, const std::string &clientip, const uint16_t &clientport)
    {
        while(true)
        {
            // 1.接受数据
            char buffer[1024];
            int n=recv(sockfd,buffer,sizeof(buffer)-1,0);//在这里认为一下子读取到所有数据
            if(n>0)
            {
                buffer[n]=0;
            }
            else
            {
                logMessage(Debug,"quit...");
            }
            // 2.处理数据
            std::string sendstring=_func(buffer);
            // 3.发送数据
            send(sockfd,sendstring.c_str(),sendstring.size(),0);
        }
    }

    void Start()
    {
        while (true)
        {
            std::string clinetip;
            uint16_t clientport;
            int sockfd = _listensock.Accept(&clinetip, &clientport);
            if (sockfd)
                continue;
            pthread_t tid;
            pthreadData *td = new pthreadData(this, sockfd, clinetip, clientport);
            pthread_create(&tid, nullptr, threadRoutine, td);
        }
    }
    ~HttpServer() {}

private:
    uint16_t _port;
    func_t _func;
    Sock _listensock;
};